package com.aios.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.aios.dao.DoorMapper;
import com.aios.dao.IrisUserHasDoorMapper;
import com.aios.dao.UserGroupHasDoorMapper;
import com.aios.entity.Door;
import com.aios.entity.IrisUserHasDoor;
import com.aios.entity.IrisUserHasDoorKey;
import com.aios.entity.UserGroupHasDoor;
import com.aios.entity.UserGroupHasDoorKey;
import com.aios.entity.mapper.AssignedState;
import com.aios.entity.mapper.DoorHasUsers;
import com.aios.entity.unit.StatusEnum;
import com.aios.service.DoorService;
import com.aios.service.ExistValidationEnum;
import com.aios.util.ListCompare;
import com.aios.util.Pager;

@Service("doorService")
public class DoorServiceImpl extends AbstractListService implements DoorService {

	@Autowired
	private DoorMapper doorMapper;

	@Autowired
	private IrisUserHasDoorMapper irisUserHasDoorMapper;

	@Autowired
	private UserGroupHasDoorMapper userGroupHasDoorMapper;

	@Override
	public List<Door> findAll() {
		return doorMapper.findAllByStatus(0);
	}

	@Override
	public List<Door> findAllNotDisabled() {
		return doorMapper.findAllByStatus(0);
	}

	@Override
	public List<Door> findAllDisabled() {
		return doorMapper.findAllByStatus(1);
	}

	@Override
	public Door findById(Integer id) {
		return doorMapper.selectByPrimaryKey(id);
	}

	@Override
	public int save(Door entity) {
		return doorMapper.insertSelective(entity);
	}

	@Override
	public int save(Door entity, Integer systemUserID) {
		saveAddSettings(entity, systemUserID);

		return doorMapper.insertSelective(entity);
	}

	@Override
	public int update(Door entity) {
		return doorMapper.updateByPrimaryKeySelective(entity);
	}

	@Override
	public int update(Door entity, Integer systemUserID) {
		saveEditSettings(entity, systemUserID);
		return doorMapper.updateByPrimaryKeySelective(entity);
	}

	@Override
	public int delete(Door entity) {
		return delete(entity.getId());
	}

	@Override
	public int delete(Integer id) {
		return doorMapper.deleteByPrimaryKey(id);
	}

	@Override
	public ExistValidationEnum validateDoorName(String doorName) {
		List<Door> list = doorMapper.findByDoorName(doorName);

		if (list.size() == 1) {
			return ExistValidationEnum.EXIST;
		} else if (list.size() > 1) {
			return ExistValidationEnum.MULTIPLE_EXIST;
		} else {
			return ExistValidationEnum.NOT_EXIST;
		}
	}
	
	@Override
	public ExistValidationEnum validateDoorName(String doorName, Integer id) {
		List<Door> list = doorMapper.findDoorNameNotWithId(doorName,id);

		if (list.size() == 1) {
			return ExistValidationEnum.EXIST;
		} else if (list.size() > 1) {
			return ExistValidationEnum.MULTIPLE_EXIST;
		} else {
			return ExistValidationEnum.NOT_EXIST;
		}
	}

	@Override
	public List<AssignedState> findAssignedGroupsByDoorId(Integer doorId) {
		return doorMapper.findAssignedGroups(doorId);
	}

	@Override
	public List<AssignedState> findAssignedUsersByDoorId(Integer doorId) {
		return doorMapper.findAssignedUsers(doorId);
	}

	@Override
	public List<AssignedState> findAvailableGroupsByDoorId(Integer doorId) {
		return doorMapper.findAvailableGroups(doorId);
	}

	@Override
	public List<AssignedState> findAvailableUsersByDoorId(Integer doorId) {
		return doorMapper.findAvailableUsers(doorId);
	}

	@Override
	public List<DoorHasUsers> findUsersForDoors() {

		return doorMapper.findUsersForDoors(StatusEnum.ACTIVE.getStatusValue());
	}

	@Override
	public Pager viewPaginatedActiveList(Integer start, Integer size) {
		prepare(start, size);

		try {
			pager.setTotal(doorMapper.countAllByStatus(StatusEnum.ACTIVE.getStatusValue()));
			pager.setList(doorMapper.findPaginatedList(StatusEnum.ACTIVE.getStatusValue(), start, size));
		} catch (Exception e) {
			// logger
			e.printStackTrace();
		}

		return pager;
	}

	@Override
	public int updateGroupList(Door door, List<Integer> selectedGroupList,Integer systemUserId) {
		
		int returnValue = 0;
		
		if (selectedGroupList == null) {
			selectedGroupList = new ArrayList<Integer>();
		}

		List<Integer> existingGroupList = this.userGroupHasDoorMapper
				.findExistingGroupList(door.getId());

		List<Integer> differenceList = ListCompare.getDifference(
				selectedGroupList, existingGroupList);

		if (!(differenceList.isEmpty())) {
			returnValue = this.removeUncheckedList(door.getId(),
					differenceList, "group");
		}

		differenceList = ListCompare.getDifference(existingGroupList,
				selectedGroupList);

		if (!(differenceList.isEmpty())) {
			returnValue = this.insertNewList(door.getId(), differenceList,
					systemUserId, "group");
		}

		return returnValue;

	}

	@Override
	public int updateUserList(Door door, List<Integer> selectedUserList,
			Integer systemUserId) {
		int returnValue = 0;

		if (selectedUserList == null) {
			selectedUserList = new ArrayList<Integer>();
		}

		List<Integer> existingUserList = this.irisUserHasDoorMapper
				.findExistingUserList(door.getId());

		List<Integer> differenceList = ListCompare.getDifference(
				selectedUserList, existingUserList);

		if (!(differenceList.isEmpty())) {
			returnValue = this.removeUncheckedList(door.getId(),
					differenceList, "user");
		}

		differenceList = ListCompare.getDifference(existingUserList,
				selectedUserList);

		if (!(differenceList.isEmpty())) {
			returnValue = this.insertNewList(door.getId(), differenceList,
					systemUserId, "user");
		}

		return returnValue;

	}

	private int insertNewList(Integer doorID, List<Integer> insertIdList,
			Integer systemUserID, String listType) {
		int returnValue = 0;
		if (insertIdList != null) {

			for (int i = 0; i < insertIdList.size(); i++) {

				if (listType.equals("user")) {
					IrisUserHasDoor irisUserHasDoor = new IrisUserHasDoor();
					irisUserHasDoor.setDoorId(doorID);
					irisUserHasDoor.setIrisUserId(insertIdList.get(i));
					saveAddSettings(irisUserHasDoor, systemUserID);
					returnValue = this.irisUserHasDoorMapper
							.insertSelective(irisUserHasDoor);
				}

				else if (listType.equals("group")) {
					UserGroupHasDoor userGroupHasDoor = new UserGroupHasDoor();
					userGroupHasDoor.setDoorId(doorID);
					userGroupHasDoor.setUserGroupId(insertIdList.get(i));
					saveAddSettings(userGroupHasDoor, systemUserID);
					returnValue = this.userGroupHasDoorMapper
							.insert(userGroupHasDoor);
				}

			}
		}
		return returnValue;
	}

	private int removeUncheckedList(Integer doorID, List<Integer> removeIdList,
			String listType) {

		int returnValue = 0;
		
		for (int i = 0; i < removeIdList.size(); i++) {
			if (listType.equals("user")) {
				IrisUserHasDoorKey key = new IrisUserHasDoorKey();
				key.setDoorId(doorID);
				key.setIrisUserId(removeIdList.get(i));
				returnValue = this.irisUserHasDoorMapper
						.deleteByPrimaryKey(key);
			} else if (listType.equals("group")) {
				UserGroupHasDoorKey key = new UserGroupHasDoorKey();
				key.setDoorId(doorID);
				key.setUserGroupId(removeIdList.get(i));
				returnValue = this.userGroupHasDoorMapper
						.deleteByPrimaryKey(key);
			}

		}
		
		return returnValue;
	}

	@Override
	public int saveUserList(Door door, List<Integer> selectedUserList,
			Integer systemUserId) {
		return insertNewList(door.getId(), selectedUserList, systemUserId,
				"user");
	}

	@Override
	public int saveGroupList(Door door, List<Integer> selectedGroupList,
			Integer systemUserId) {
		return insertNewList(door.getId(), selectedGroupList, systemUserId,
				"group");
	}

	@Override
	public int findIdByDoorName(String doorName) {
		return doorMapper.findByDoorName(doorName).get(0).getId();
	}

	@Override
	public DoorHasUsers findByIdWithUserGroup(Integer doorId) {
		return doorMapper.findByIdWithUserAndGroup(doorId);
	}

	@Override
	public int getCount() {
		return doorMapper.countAllByStatus(0);
	}

}
